﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

using log4net;
using CureConsulting.DataAccess;

using Blog.Net.Business.BusinessObjects;
using Blog.Net.DataAccess.DataControls;

namespace SimplePHPBlogImport
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                log4net.Config.XmlConfigurator.Configure();
                IList<BlogResponseBO> commentList = new List<BlogResponseBO>();

                foreach (string arg in args)
                {
                    //if (arg.ToLower() == "-c")
                    //NHibernateDBUtils.CreateTables();
                    //NHibernateDBUtils.CreateSqlScript("testfile.sql");
                }

                string importPath = null;
                foreach (string arg in args)
                {
                    if (!arg.StartsWith("-"))
                        importPath = arg;
                }

                if (!string.IsNullOrEmpty(importPath))
                {
                    string configPath = Path.Combine(importPath, "config");
                    if (File.Exists(Path.Combine(configPath, "categories.txt")))
                        createCategories(Path.Combine(configPath, "categories.txt"));
                    else
                        oldNewCategoryId = new Dictionary<int, int>();

                    string[] years = Directory.GetDirectories(Path.Combine(importPath, "content"));
                    foreach (string year in years)
                    {
                        log.DebugFormat("  {0}\r\n", year.Substring(year.LastIndexOf('\\')));
                        string[] months = Directory.GetDirectories(year);
                        foreach (string month in months)
                        {
                            log.DebugFormat("      {0}\r\n", month.Substring(month.LastIndexOf('\\')));
                            string[] entries = Directory.GetFiles(month, "*.txt");
                            foreach (string entry in entries)
                            {
                                commentList = new List<BlogResponseBO>();
                                log.DebugFormat("          {0}\r\n", entry.Substring(entry.LastIndexOf('\\')));
                                StreamReader tr = new StreamReader(entry, Encoding.GetEncoding("iso-8859-1"));
                                string entryText = tr.ReadToEnd();
                                string ratingText = null;
                                string directory = entry.Remove(entry.LastIndexOf('.'));
                                int views = -1;
                                if (Directory.Exists(directory))
                                {
                                    string ratingFile = Path.Combine(directory, "rating.txt");
                                    if (File.Exists(ratingFile))
                                    {
                                        tr = new StreamReader(ratingFile);
                                        ratingText = tr.ReadToEnd();
                                    }
                                    string viewsFile = Path.Combine(directory, "view_counter.txt");
                                    if (File.Exists(viewsFile))
                                    {
                                        tr = new StreamReader(viewsFile);
                                        views = int.Parse(tr.ReadToEnd());
                                    }
                                    string commentsDir = Path.Combine(directory, "comments");
                                    if (Directory.Exists(commentsDir))
                                    {
                                        string[] comments = Directory.GetFiles(commentsDir, "*.txt");
                                        foreach (string commentFile in comments)
                                        {
                                            tr = new StreamReader(commentFile);
                                            string comment = tr.ReadToEnd();
                                            Dictionary<string, string> oldComment = splitText(comment);
                                            commentList.Add(new BlogResponseBO(oldComment["NAME"], oldComment.ContainsKey("EMAIL") ? oldComment["EMAIL"] : null, oldComment["CONTENT"], getDate(oldComment["DATE"]), null));
                                        }
                                    }
                                }
                                addBlogEntry(entryText, ratingText, views, commentList);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private static Dictionary<int, int> oldNewCategoryId;
        private static ILog log = log4net.LogManager.GetLogger(typeof(Program));

        private static void createCategories(string categoryFileName)
        {
            TextReader tr = new StreamReader(categoryFileName);
            oldNewCategoryId = new Dictionary<int, int>();

            string categories = tr.ReadToEnd();
            string[] pieces = categories.Split('|');
            Dictionary<int, int> depth = new Dictionary<int, int>();
            for (int i = 0; i < pieces.Length; i += 3)
            {
                BlogCategoryBO category = new BlogCategoryBO();
                category.Name = pieces[i + 1];
                //if (int.Parse(pieces[i + 2]) > 0 && depth.ContainsKey(int.Parse(pieces[i + 2]) - 2))
                //    category.ParentId = depth[int.Parse(pieces[i + 2]) - 2];

                BlogCategoryDataControl.Instance.Save(category);

                // Save the old and new id's for later
                oldNewCategoryId.Add(int.Parse(pieces[i]), (int)category.Id);

                if (pieces[i + 2] == "0")
                {
                    depth = new Dictionary<int, int>();
                    depth.Add(int.Parse(pieces[i + 2]), (int)category.Id);
                }
                else
                {
                    if (!depth.ContainsKey(int.Parse(pieces[i + 2])))
                        depth.Add(int.Parse(pieces[i + 2]), (int)category.Id);
                    else
                        depth[int.Parse(pieces[i + 2])] = (int)category.Id;
                }
            }
        }

        private static void addBlogEntry(string entryText, string ratingText, int views, IList<BlogResponseBO> commentList)
        {
            try
            {
                string[] categories = new string[0];
                Dictionary<string, string> oldEntry = splitText(entryText);
                Dictionary<string, string> oldRating = splitText(ratingText);

                if (oldEntry.ContainsKey("CATEGORIES"))
                    categories = oldEntry["CATEGORIES"].Split(',');

                string subject = oldEntry["SUBJECT"];
                subject = subject.Replace(Convert.ToChar(147).ToString(), "\"").Replace(Convert.ToChar(148).ToString(), "\" ");
                subject = subject.Replace(Convert.ToChar(146).ToString(), "'");

                string content = Regex.Replace(oldEntry["CONTENT"], "\\[url=(?<url>.*?)\\](?<link>.*?)\\[/url\\]", "<a href=\"${url}\">${link}</a>");
                content = content.Replace("[pre]", "<pre>").Replace("[/pre]", "</pre>");
                content = content.Replace("[b]", "<strong>").Replace("[/b]", "</strong>");
                content = content.Replace("[i]", "<i>").Replace("[/i]", "</i>");
                content = content.Replace(Convert.ToChar(147).ToString(), "\"").Replace(Convert.ToChar(148).ToString(), "\" ");
                content = content.Replace(Convert.ToChar(146).ToString(), "'");
                content = content.Replace("\r\n", "<br/>");

                BlogEntryBO blogEntry = new BlogEntryBO(subject, null, content, views, oldRating.ContainsKey("POINTS") ? int.Parse(oldRating["POINTS"]) : 0, oldRating.ContainsKey("VOTES") ? int.Parse(oldRating["VOTES"]) : 0, getDate(oldEntry["DATE"]));

                foreach (string category in categories)
                {
                    int oldCategory = int.Parse(category);
                    if (oldNewCategoryId.ContainsKey(oldCategory))
                        blogEntry.BlogCategories.Add(new BlogCategoryBO(oldNewCategoryId[oldCategory]));
                }

                foreach (BlogResponseBO response in commentList)
                {
                    response.BlogEntry = blogEntry;
                    blogEntry.BlogResponses.Add(response);
                }

                BlogEntryDataControl.Instance.Save(blogEntry);
            }
            catch (Exception ex)
            {
                log.Error(ex);
                log.DebugFormat("Entry: {0}", entryText);
                log.DebugFormat("Rating: {0}", ratingText);
                log.DebugFormat("Views: {0}", views);
                log.DebugFormat("Comments: {0}", commentList.Count);
            }
        }

        private static Dictionary<string, string> splitText(string entryText)
        {
            string[] split = entryText.Split('|');
            Dictionary<string, string> entry = new Dictionary<string, string>();
            for (int i = 0; i < split.Length; i += 2)
            {
                entry.Add(split[i].ToUpper(), split[i + 1]);
            }
            return entry;
        }

        private static DateTime getDate(string date)
        {
            return DateTime.Parse("1/1/1970").AddSeconds(double.Parse(date));
        }

        private static void createDB_Click(object sender, EventArgs e)
        {
            NHibernateDBUtils.CreateTables();
        }
    }
}
